/*********************************************************************************************
 * 
 * 
 * 'WebDisplaySurface.java', in plugin 'msi.gama.display.web', is part of the source code of the
 * GAMA modeling and simulation platform.
 * (c) 2007-2014 UMI 209 UMMISCO IRD/UPMC & Partners
 * 
 * Visit https://code.google.com/p/gama-platform/ for license information and developers contact.
 * 
 * 
 **********************************************************************************************/
package msi.gama.display.web;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.Point;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;

import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Vector3f;

import msi.gama.common.interfaces.IDisplaySurface;
import msi.gama.common.interfaces.IGamaView;
import msi.gama.common.interfaces.ILayerManager;
import msi.gama.display.web.utils.Logger;
import msi.gama.gui.displays.awt.AbstractAWTDisplaySurface;
import msi.gama.gui.swt.SwtGui;
import msi.gama.gui.views.WebDisplayView;
import msi.gama.metamodel.agent.IAgent;
import msi.gama.metamodel.shape.GamaPoint;
import msi.gama.metamodel.shape.ILocation;
import msi.gama.metamodel.shape.IShape;
import msi.gama.outputs.LayeredDisplayOutput;
import msi.gama.outputs.display.LayerManager;
import msi.gama.precompiler.GamlAnnotations.display;
import msi.gama.runtime.IScope;
import msi.gama.util.IList;
import my1024.app.MainApp;

import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;

import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.SimpleUniverse;

@display("web")
public class WebDisplaySurface extends AbstractAWTDisplaySurface implements IDisplaySurface {
	private static final long serialVersionUID = -1821138915295131765L;
	private static final String TAG = WebDisplaySurface.class.getName();

	public WebDisplaySurface(final Object... args) {
	}

	@Override
	public IScope getDisplayScope() {
		return null;
	}

	/**
	 * Method getImage()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getImage()
	 */
	@Override
	public BufferedImage getImage() {
		return null;
	}

	/**
	 * Method dispose()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#dispose()
	 */
	@Override
	public void dispose() {
	}

	/**
	 * Method updateDisplay()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#updateDisplay()
	 */
	@Override
	public void updateDisplay() {
		if (isWebDisplayViewNotFound()) {
			findWebDisplayView();
		}
	}

	/**
	 * Method forceUpdateDisplay()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#forceUpdateDisplay()
	 */
	@Override
	public void forceUpdateDisplay() {
	}

	/**
	 * Method computeBoundsFrom()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#computeBoundsFrom(int,
	 *      int)
	 */
	@Override
	public int[] computeBoundsFrom(final int width, final int height) {
		return null;
	}

	/**
	 * Method resizeImage()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#resizeImage(int, int)
	 */
	@Override
	public boolean resizeImage(final int width, final int height) {
		return false;
	}

	/**
	 * Method zoomIn()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#zoomIn()
	 */
	@Override
	public void zoomIn() {
	}

	/**
	 * Method zoomOut()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#zoomOut()
	 */
	@Override
	public void zoomOut() {
	}

	/**
	 * Method zoomFit()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#zoomFit()
	 */
	@Override
	public void zoomFit() {
	}

	/**
	 * Method getManager()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getManager()
	 */
	@Override
	public ILayerManager getManager() {
		return new LayerManager(this);
	}

	/**
	 * Method focusOn()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#focusOn(msi.gama.metamodel.shape.IShape,
	 *      msi.gama.common.interfaces.ILayer)
	 */
	@Override
	public void focusOn(final IShape geometry) {
	}

	/**
	 * Method canBeUpdated()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#canBeUpdated()
	 */
	@Override
	public boolean canBeUpdated() {
		return false;
	}

	/**
	 * Method canBeUpdated()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#canBeUpdated(boolean)
	 */
	@Override
	public void canBeUpdated(final boolean ok) {
	}

	/**
	 * Method setBackgroundColor()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setBackgroundColor(java.awt.Color)
	 */
	@Override
	public void setBackgroundColor(final Color background) {
	}

	/**
	 * Method setPaused()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setPaused(boolean)
	 */
	@Override
	public void setPaused(final boolean b) {
	}

	/**
	 * Method isPaused()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#isPaused()
	 */
	@Override
	public boolean isPaused() {
		return false;
	}

	/**
	 * Method setQualityRendering()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setQualityRendering(boolean)
	 */
	@Override
	public void setQualityRendering(final boolean quality) {
	}

	/**
	 * Method setSynchronized()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setSynchronized(boolean)
	 */
	@Override
	public void setSynchronized(final boolean checked) {
	}

	/**
	 * Method setAutoSave()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setAutoSave(boolean, int,
	 *      int)
	 */
	@Override
	public void setAutoSave(final boolean autosave, final int x, final int y) {
	}

	/**
	 * Method initOutput3D()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#initOutput3D(boolean,
	 *      msi.gama.metamodel.shape.ILocation)
	 */
	@Override
	public void initOutput3D(final boolean output3d, final ILocation output3dNbCycles) {
	}

	/**
	 * Method setSnapshotFileName()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setSnapshotFileName(java.lang.String)
	 */
	@Override
	public void setSnapshotFileName(final String string) {
	}

	/**
	 * Method snapshot()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#snapshot()
	 */
	@Override
	public void snapshot() {
	}

	/**
	 * Method getWidth()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getWidth()
	 */
	@Override
	public int getWidth() {
		return 0;
	}

	/**
	 * Method getHeight()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getHeight()
	 */
	@Override
	public int getHeight() {
		return 0;
	}

	/**
	 * Method getImageWidth()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getImageWidth()
	 */
	@Override
	public int getImageWidth() {
		return 0;
	}

	/**
	 * Method getImageHeight()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getImageHeight()
	 */
	@Override
	public int getImageHeight() {
		return 0;
	}

	/**
	 * Method setOrigin()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setOrigin(int, int)
	 */
	@Override
	public void setOrigin(final int i, final int j) {
	}

	/**
	 * Method getOriginX()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getOriginX()
	 */
	@Override
	public int getOriginX() {
		return 0;
	}

	/**
	 * Method getOriginY()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getOriginY()
	 */
	@Override
	public int getOriginY() {
		return 0;
	}

	/**
	 * Method initialize()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#initialize(double,
	 *      double, msi.gama.outputs.LayeredDisplayOutput)
	 */
	private String fullViewName = "";

	@Override
	public void initialize(final IScope scope, final double w, final double h,
			final LayeredDisplayOutput output) {

		final String viewId = output.getViewId();
		String viewName = output.getViewName();
		this.fullViewName = viewId + ":" + viewName;
	}

	/**
	 * Method outputChanged()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#outputChanged(double,
	 *      double, msi.gama.outputs.LayeredDisplayOutput)
	 */
	@Override
	public void outputChanged(final IScope scope, final double env_width,
			final double env_height,
			final LayeredDisplayOutput output) {
	}

	/**
	 * Method getHighlightColor()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getHighlightColor()
	 */
	@Override
	public int[] getHighlightColor() {
		return null;
	}

	/**
	 * Method setHighlightColor()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setHighlightColor(int[])
	 */
	@Override
	public void setHighlightColor(final int[] rgb) {
	}

	/**
	 * Method addMouseListener()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#addMouseListener(java.awt.event.MouseListener)
	 */
	@Override
	public void addMouseListener(final MouseListener e) {
	}

	/**
	 * Method getEnvWidth()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getEnvWidth()
	 */
	@Override
	public double getEnvWidth() {
		return 0;
	}

	/**
	 * Method getEnvHeight()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getEnvHeight()
	 */
	@Override
	public double getEnvHeight() {
		return 0;
	}

	/**
	 * Method getDisplayWidth()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getDisplayWidth()
	 */
	@Override
	public int getDisplayWidth() {
		return 0;
	}

	/**
	 * Method getDisplayHeight()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getDisplayHeight()
	 */
	@Override
	public int getDisplayHeight() {
		return 0;
	}

	/**
	 * Method setZoomListener()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setZoomListener(msi.gama.common.interfaces.IDisplaySurface.IZoomListener)
	 */
	@Override
	public void setZoomListener(final IZoomListener listener) {
	}

	/**
	 * Method getModelCoordinates()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getModelCoordinates()
	 */
	@Override
	public GamaPoint getModelCoordinates() {
		return null;
	}

	/**
	 * Method isSynchronized()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#isSynchronized()
	 */
	@Override
	public boolean isSynchronized() {
		return false;
	}

	/**
	 * Method followAgent()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#followAgent(msi.gama.metamodel.agent.IAgent)
	 */
	@Override
	public void followAgent(final IAgent a) {
	}

	/**
	 * Method getZoomLevel()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getZoomLevel()
	 */
	@Override
	public double getZoomLevel() {
		return 0;
	}

	/**
	 * Method setSize()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#setSize(int, int)
	 */
	@Override
	public void setSize(final int x, final int y) {
	}

	/**
	 * Method getQualityRendering()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#getQualityRendering()
	 */
	@Override
	public boolean getQualityRendering() {
		return false;
	}

	/**
	 * Method removeMouseListener()
	 * 
	 * @see msi.gama.common.interfaces.IDisplaySurface#removeMouseListener(java.awt.event.MouseListener)
	 */
	@Override
	public void removeMouseListener(final MouseListener e) {
	}

	@Override
	public GamaPoint getModelCoordinatesFrom(final int xOnScreen, final int yOnScreen,
			final Point sizeInPixels,
			final Point positionInPixels) {
		return null;
	}

	@Override
	public IList<IAgent> selectAgent(final int x, final int y) {
		return null;
	}

	@Override
	protected void createIGraphics() {
	}

	@Override
	protected Double computeInitialZoomLevel() {
		return null;
	}

	public void debugViewId() {
		traceViews();

		final IWorkbenchPage page = SwtGui.getPage();
		if (page == null) {
			Logger.elog(TAG, "Page null");
			return;
		} // Closing the workbench
		final IViewReference ref = page.findViewReference(WebDisplayView.ID);
		if (ref == null) {
			Logger.elog(TAG, "View Ref null");
			return;
		}
		final IViewPart part = ref.getView(true);
		if (!(part instanceof IGamaView)) {
			Logger.elog(TAG, "Not view display");
			return;
		}
		final IGamaView view = (IGamaView) part;
		Logger.elog(TAG, "View OK");
	}

	public void traceViews() {
		SwtGui.getDisplay().syncExec(new Runnable() {

			@Override
			public void run() {
				try {
					IViewReference[] result = SwtGui.getPage().getViewReferences();

					for (IViewReference view : result) {
						Logger.mlog(view.getId());
					}
				} catch (final Exception e) {
					e.printStackTrace();
				}

			}
		});
	}

	private WebDisplayView webDisplayView = null;

	private boolean isWebDisplayViewNotFound() {
		return null == this.webDisplayView;
	}

	private Frame awt;

	public void findWebDisplayView() {
		SwtGui.getDisplay().syncExec(new Runnable() {

			@Override
			public void run() {
				try {
					IViewReference[] listViews = SwtGui.getPage().getViewReferences();

					for (IViewReference viewRef : listViews) {
						if (viewRef.getId().equals(fullViewName)) {
							webDisplayView = (WebDisplayView) viewRef.getView(true);

							Composite component = webDisplayView.getComponent();
							awt = SWT_AWT.new_Frame(component);
							awt.setLayout(new BorderLayout());

							MainApp app = new MainApp();
							awt.add(app.drawingPanel, BorderLayout.CENTER);
						}
					}
				} catch (final Exception e) {
					e.printStackTrace();
				}

			}
		});
	}

	private void showDemo() {
		GraphicsConfiguration cf = SimpleUniverse.getPreferredConfiguration();
		Canvas3D canvas = new Canvas3D(cf);
		SimpleUniverse univer = new SimpleUniverse(canvas);
		Transform3D t = new Transform3D();
		t.rotX(Math.PI / 4.0);
		t.setTranslation(new Vector3f(0f, 0f, -5f));

		TransformGroup tg = new TransformGroup(t);
		tg.addChild(new ColorCube(0.2f));

		BranchGroup bg = new BranchGroup();
		bg.addChild(tg);

		univer.getViewingPlatform().setNominalViewingTransform();

		awt.add(canvas, BorderLayout.CENTER);
	}

	Browser internalBrowser;

	private void testInternalBrowser() {

		SwtGui.getDisplay().syncExec(new Runnable() {

			static final String webUrl = "http://get.webgl.org/";

			@Override
			public void run() {
				try {
					internalBrowser.setUrl(webUrl);
				} catch (final Exception e) {
					e.printStackTrace();
				}

			}
		});
	}

}
